#include "../DataModule.h"

#include <list>

enum FieldType { FT_VAL_USIGNED, FT_VAL_SIGNED, FT_ADDR, FT_TEXT, FT_BITS };

struct Argument {
  uint val;
  char* name;

  Argument(uint val, const char* name);
  ~Argument();
};

struct BitField {
  char* name;
  int length, base;
  std::list<Argument*> args;

  BitField(const char* name, int length, int base);
  ~BitField();
  uint getValFromStr(const char* str);
  void getValAsStr(uint val, char* out);
};

struct TableField {
  char* name;
  FieldType type;
  int length, base, num_entries;
  void* data;
  std::list<Argument*> args;
  std::list<BitField*> bits;

  TableField(const char* name, FieldType type, int length, int num_entries);
  ~TableField();

  void setBase(int base);
  void setAddrType(bool hexAddr);
  void getEntryAsStr(int num, char* out);
  void setEntryAsStr(int num, const char* str, std::map<std::string, int> &labels);
  void addArgument(Argument* arg);
};

class Table {
  private:
    char *id, *name, *entryName;
    uint addr;
    int num_entries, entry_len, base;
    std::list<TableField*> tfs;
  public:
    Table(const char* id, const char* name, const char* entryName, uint addr, int num_entries, int base);
    ~Table();

    void addField(TableField* tf);
    int getNumEntries();

    void readFromRom(Rom& rom);
    void writeToRom(Rom& rom);
    void readFromXml(char* dirName, std::map<std::string, std::string> &fns, std::map<std::string, int> &labels);
    void writeToXml(char* dirName, std::map<std::string, std::string> &fns);
};

class TableModule: public DataModule {
  private:
    std::list<Table*> tables;
  public:
    TableModule(const char* tblFname);
    ~TableModule();

    const char* getName();
    const char* getCredits();

    void readFromRom(Rom& rom);
    void writeToRom(Rom& rom);
    void readFromDat(char* dirName, std::map<std::string, std::string> &fns, std::map<std::string, int> &labels);
    void writeToDat(char* dirName, std::map<std::string, std::string> &fns);
};
